package userlogic

import (
	"context"

	"go-zero-admin/apps/system/cmd/rpc/internal/logic/dept"
	"go-zero-admin/apps/system/cmd/rpc/internal/logic/userscope"
	"go-zero-admin/apps/system/cmd/rpc/internal/svc"
	"go-zero-admin/apps/system/cmd/rpc/syspb"
	"go-zero-admin/pkg/constant"
	"go-zero-admin/pkg/tool"
	"go-zero-admin/pkg/xerr"

	"github.com/Masterminds/squirrel"
	"github.com/jinzhu/copier"
	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/logx"
)

type GetUserListLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
	getDeptListLogic      *deptlogic.GetDeptListLogic
	getDeptSonByPidLogic  *deptlogic.GetDeptSonByPidLogic
	getUserDataScopeLogic *userscopelogic.GetUserDataScopeLogic
}

func NewGetUserListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserListLogic {
	return &GetUserListLogic{
		ctx:                   ctx,
		svcCtx:                svcCtx,
		Logger:                logx.WithContext(ctx),
		getDeptListLogic:      deptlogic.NewGetDeptListLogic(ctx, svcCtx),
		getDeptSonByPidLogic:  deptlogic.NewGetDeptSonByPidLogic(ctx, svcCtx),
		getUserDataScopeLogic: userscopelogic.NewGetUserDataScopeLogic(ctx, svcCtx),
	}
}

func (l *GetUserListLogic) GetUserList(in *syspb.GetUserListReq) (*syspb.GetUserListResp, error) {
	listWhereBuilder := l.svcCtx.SysUserModel.RowBuilder()
	countWhereBuilder := l.svcCtx.SysUserModel.CountBuilder("1")
	if in.GetKeyWords() != "" {
		condition := squirrel.Or{
			squirrel.Like{"user_name": in.GetKeyWords() + "%"},
			squirrel.Like{"user_nickname": in.GetKeyWords() + "%"},
		}
		listWhereBuilder = listWhereBuilder.Where(condition)
		countWhereBuilder = countWhereBuilder.Where(condition)
	}
	if in.GetMobile() != "" {
		condition := squirrel.Like{"mobile": in.GetMobile() + "%"}
		listWhereBuilder = listWhereBuilder.Where(condition)
		countWhereBuilder = countWhereBuilder.Where(condition)
	}
	if in.GetIsExNameOrMobileOrEmail() && in.GetUserName() != "" && in.GetMobile() != "" && in.GetEmail() != "" {
		condition := squirrel.Or{
			squirrel.Eq{"user_name": in.GetUserName()},
			squirrel.Eq{"mobile": in.GetMobile()},
			squirrel.Eq{"user_email": in.GetEmail()},
		}
		listWhereBuilder = listWhereBuilder.Where(condition)
		countWhereBuilder = countWhereBuilder.Where(condition)
	}
	if in.GetIsNotId() != 0 {
		conditionEx := squirrel.NotEq{"id": in.GetIsNotId()}
		listWhereBuilder = listWhereBuilder.Where(conditionEx)
		countWhereBuilder = countWhereBuilder.Where(conditionEx)
	}
	if in.GetStatus() != "" {
		condition := squirrel.Eq{"user_status": in.GetStatus()}
		listWhereBuilder = listWhereBuilder.Where(condition)
		countWhereBuilder = countWhereBuilder.Where(condition)
	}
	if len(in.GetDeptIds()) > 0 {
		condition := squirrel.Eq{"dept_id": in.GetDeptIds()}
		listWhereBuilder = listWhereBuilder.Where(condition)
		countWhereBuilder = countWhereBuilder.Where(condition)
	}
	// 获取当前部门以及其子部门的部门Id集合
	// 用于点击部门获取该部门及其子部门下的所有人员信息
	if in.GetSonIdsByDeptId() != 0 {
		condition := squirrel.Eq{"dept_id": l.getDeptIdAndSonIds(in.GetSonIdsByDeptId())}
		listWhereBuilder = listWhereBuilder.Where(condition)
		countWhereBuilder = countWhereBuilder.Where(condition)
	}
	if len(in.GetPage().GetDateRange()) > 0 {
		condition := squirrel.And{squirrel.GtOrEq{"create_time": in.GetPage().GetDateRange()[0]},
			squirrel.LtOrEq{"create_time": in.GetPage().GetDateRange()[1]}}
		listWhereBuilder = listWhereBuilder.Where(condition)
		countWhereBuilder = countWhereBuilder.Where(condition)
	}
	if in.GetIsDataScope() {
		dataScopeList := l.getUserDataScopeLogic.GetDataScopeBuilder(in.GetDataScopeUserId(),
			"dept_id", "create_user")
		for _, v := range dataScopeList {
			listWhereBuilder = listWhereBuilder.Where(v)
			countWhereBuilder = countWhereBuilder.Where(v)
		}
	}

	// 查询
	if in.GetPage() != nil && in.GetPage().GetIsPage() {
		return l.getPage(in, listWhereBuilder, countWhereBuilder)
	} else if in.GetPage() != nil && in.GetPage().GetIsCount() {
		return l.getCount(in, countWhereBuilder)
	}
	return l.getList(in, listWhereBuilder)
}

func (l *GetUserListLogic) getList(in *syspb.GetUserListReq,
	whereBuilder squirrel.SelectBuilder) (*syspb.GetUserListResp, error) {
	orderBy := "id desc"
	if in.GetPage() != nil {
		orderBy = in.GetPage().GetOrderBy()
	}
	list, err := l.svcCtx.SysUserModel.FindAll(l.ctx, whereBuilder, orderBy)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DbError),
			tool.GetErrMsgFormat("get user list"), err, in)
	}

	// 处理数据
	var dataList []*syspb.SysUser
	for _, v := range list {
		var data syspb.SysUser
		_ = copier.Copy(&data, v)

		data.UpdateTime = v.UpdateTime.Unix()
		data.CreateTime = v.CreateTime.Unix()

		dataList = append(dataList, &data)
	}

	return &syspb.GetUserListResp{
		List: dataList,
	}, nil
}

func (l *GetUserListLogic) getPage(in *syspb.GetUserListReq, listWhereBuilder squirrel.SelectBuilder,
	countWhereBuilder squirrel.SelectBuilder) (*syspb.GetUserListResp, error) {
	// 分页条件
	pageNum := in.GetPage().GetPageNum()
	if pageNum == 0 {
		pageNum = 1
	}
	pageSize := in.GetPage().GetPageSize()
	if pageSize == 0 {
		pageSize = constant.PageSize
	}
	orderBy := in.GetPage().GetOrderBy()
	if orderBy == "" {
		orderBy = "id desc"
	}

	// 分页查询
	list, err := l.svcCtx.SysUserModel.FindPageListByPage(l.ctx, listWhereBuilder, pageNum, pageSize, orderBy)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DbError),
			tool.GetErrMsgFormat("get user list"), err, in)
	}
	count, err := l.svcCtx.SysUserModel.FindCount(l.ctx, countWhereBuilder)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DbError),
			tool.GetErrMsgFormat("get user count"), err, in)
	}

	// 处理数据
	var dataList []*syspb.SysUser
	for _, v := range list {
		var data syspb.SysUser
		_ = copier.Copy(&data, v)

		data.UpdateTime = v.UpdateTime.Unix()
		data.CreateTime = v.CreateTime.Unix()

		dataList = append(dataList, &data)
	}

	return &syspb.GetUserListResp{
		List: dataList,
		Page: &syspb.PageResp{
			Current: pageNum,
			Total:   count,
		},
	}, nil
}

func (l *GetUserListLogic) getCount(in *syspb.GetUserListReq,
	whereBuilder squirrel.SelectBuilder) (*syspb.GetUserListResp, error) {
	count, err := l.svcCtx.SysUserModel.FindCount(l.ctx, whereBuilder)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DbError),
			tool.GetErrMsgFormat("get user count"), err, in)
	}

	return &syspb.GetUserListResp{
		Page: &syspb.PageResp{
			Total: count,
		},
	}, nil
}

// 获取部门子类id
func (l *GetUserListLogic) getDeptIdAndSonIds(deptId int64) []int64 {
	// 获取部门列表
	deptListResp, err := l.getDeptListLogic.GetDeptList(&syspb.GetDeptListReq{})
	if err != nil || len(deptListResp.GetList()) == 0 {
		return []int64{-1}
	}

	// 获取部门的所有子类
	childListResp, err := l.getDeptSonByPidLogic.GetDeptSonByPid(&syspb.GetDeptSonByPidReq{
		Pid:  deptId,
		List: deptListResp.GetList(),
	})
	if err != nil || len(childListResp.GetList()) == 0 {
		return []int64{deptId}
	}

	// 部门子类id
	deptIds := []int64{deptId}
	for _, v := range childListResp.GetList() {
		deptIds = append(deptIds, v.GetDeptId())
	}

	return deptIds
}
